/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "节点构建.h"


#include <节点/插座/list/list数值插座.h>
#include <节点/插座/list/list矢量插座.h>
#include <节点/插座/list/list物体插座.h>
#include <节点/插座/材质纹理插座.h>
#include <节点/插座/字符插座.h>

#include "A_引擎/引擎.h"

#include <字符串/str_分割.h>






static void on_插座参数修改更新节点(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);
	}
}

static void on_节点参数更新_重新编译(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_更新上层节点(true);

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}

static void on_更新节点_冻结(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);

		f_NT_冻结节点(节点, 节点->m_冻结数据);

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}

static void on_更新节点_缓存(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		//节点->m_数据是否以缓存 = true;

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}

static void on_清除节点缓存(S_Props& prop) {
	auto nodes = f_global_get激活节点();

	for (auto 节点 : nodes) {
		节点->f_释放缓存();
		//节点->m_数据是否以缓存 = false;

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}



static void on_更新节点_数据可视(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_Show(节点->m_显示数据);
		/*for (auto& panel : 节点->m_UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构对象指针)节点面板);
		}*/
	}
}


static void on_更新节点_修改名称(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		f_str_去路径空白字符(f_prop_Str(prop));

		节点->f_setWName(f_prop_Str(prop));
		节点->f_set是否要更新(true);
	}
}

static void on_节点手动更新(S_Props& prop) {
	auto nodes = f_global_get激活节点();

	S_节点数据::g_开启节点手动更新 = true;
	for (auto 节点 : nodes) {
		节点->f_释放缓存();
		节点->f_update();
	}

	S_节点数据::g_开启节点手动更新 = false;
}


C_节点面板* f_节点创建_UI面板构建(S_UI渲染环境& ctx, C_节点基类* data, E_节点区类型 区类型) {
	C_节点面板* plane = new C_节点面板(data, ctx, 区类型);

	uint16 socketNum = 0;
	socketNum = data->f_get输入插座数量();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输入插座(i);

		plane->f_addInSocket(socket);
	}

	socketNum = data->f_get输出插座数量();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输出插座(i);

		plane->f_addOutSocket(socket);
	}

	return plane;
}







static std::u16string f_插座数值转文本(C_插座基类* socket) {
	std::u16string t = socket->f_getTypeName() + u":";

	switch (socket->m_Type) {
		case E_值类型::e_Type_F32:
			t += f_浮点数值转宽字符串(DEF_F32插座数据(socket));
			break;
		case E_值类型::e_Type_I8:
			t += f_整数值转宽字符串(DEF_I8插座数据(socket));
			break;
		case E_值类型::e_Type_I32:
			t += f_整数值转宽字符串(DEF_I32插座数据(socket));
			break;
		case E_值类型::e_Type_UI32:
			t += f_整数值转宽字符串(DEF_UI32插座数据(socket));
			break;

		case E_值类型::e_Type_uVec2: {
			const auto& val = DEF_uVec2插座数据(socket);
			t += u"(" + f_整数值转宽字符串(val.x) + u"," + f_整数值转宽字符串(val.y) + u")";;
			break;
		}
		case E_值类型::e_Type_Vec3: {
			vec3 v = DEF_Vec3插座数据(socket);
			t += u"(" + f_浮点数值转宽字符串(v.x, 4) + u"," + f_浮点数值转宽字符串(v.y, 4) + u"," + f_浮点数值转宽字符串(v.z, 4) + u")";
			break;
		}
		case E_值类型::e_Type_iVec3: {
			ivec3 v = DEF_iVec3插座数据(socket);
			t += u"(" + f_整数值转宽字符串(v.x) + u"," + f_整数值转宽字符串(v.y) + u"," + f_整数值转宽字符串(v.z) + u")";
			break;
		}

		case E_值类型::e_Type_I8_1D: {
			const auto& val = DEF_I8插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_I32_1D: {
			const auto& val = DEF_I32插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_UI32_1D: {
			const auto& val = DEF_UI32插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_F32_1D: {
			const auto& val = DEF_F32插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}

		case E_值类型::e_Type_Vec2_1D: {
			const auto& val = DEF_Vec2插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Vec3_1D: {
			const auto& val = DEF_Vec3插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		
		case E_值类型::e_Type_iVec3_1D: {
			const auto& val = DEF_iVec3插座_1D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Mat4X4_1D: {
			const auto& val = DEF_Mat44插座_1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}

		case E_值类型::e_Type_UI32_2D: {
			const auto& val = DEF_UI32插座_2D数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}

		case E_值类型::e_Type_材质1D: {
			const auto& val = DEF_材质插座_1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_纹理_1D: {
			const auto& val = DEF_纹理插座_1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Object_1D: {
			const auto& val = DEF_物体插座_1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Mesh_1D: {
			const auto& val = DEF_网格插座_1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Bounding_1D: {
			const auto& val = DEF_包围盒插座1D数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_LineStr1D: {
			const auto& val = DEF_字符串数组插座数据(socket, 0);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		case E_值类型::e_Type_Array: {
			const auto& val = DEF_数组插座数据(socket);
			t += u"(" + f_整数值转宽字符串64(val->count) + u")";
			break;
		}
		default:
			//t = socket->f_getTypeName() + u":" + socket->m_identifier;
			break;
	}
	return t;
}






void f_节点重构_面板重构(C_节点面板* plane, C_节点基类* data, E_节点区类型 区类型) {
	plane->m_区 = 区类型;
	plane->m_NodeData = data;
	//plane->m_节点当前所在视口 = nullptr;
	
	plane->f_setOriginalPos(data->m_坐标);
}

void f_节点重构_插座重构(C_节点面板* plane, C_节点基类* data, E_节点区类型 区类型) {
	
	plane->f_releaseAllSocket();


	uint16 socketNum = 0;
	socketNum = data->f_get输入插座数量();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输入插座(i);

		plane->f_addInSocket(socket);
	}

	socketNum = data->f_get输出插座数量();
	for (uint16 i = 0; i < socketNum; ++i) {
		auto* socket = data->f_get输出插座(i);

		plane->f_addOutSocket(socket);
	}
}

void f_节点重构_面板插座重构(C_节点面板* plane, C_节点基类* node, E_节点区类型 区类型) {
	f_节点重构_面板重构(plane, node, 区类型);
	f_节点重构_插座重构(plane, node, 区类型);
}

bool f_节点重构_重构属性面板数据(C_节点面板* plane, std::vector<S_Props>& props) {
	C_节点基类* 节点 = dynamic_cast<C_节点基类*>(plane->m_NodeData);
	if(节点->m_越过更新) return false;


	S_Props Prop显示可视 = f_alloc_BoolProp(&(节点->m_显示数据), u"显示数据");
	//Prop显示可视.m_私有 = true;
	Prop显示可视.m_UI->m_Update = on_更新节点_数据可视;
	props.push_back(Prop显示可视);

	if (节点->m_自定义更新方式) {
		节点->m_更新方式属性.m_UI->m_Update = on_节点参数更新_重新编译;
		props.push_back(节点->m_更新方式属性);

		uint32 更新方式 = f_prop_UI32位域枚举(节点->m_更新方式属性);
		if (更新方式 & E_节点更新方式::e_节点更新_手动) {
			S_Props 手动执行 = f_alloc_OpsProp(on_节点手动更新, u"手动执行");
			props.push_back(手动执行);
		}
	}

	if (节点->m_开启缓存节点) {
		
		//S_Props Prop冻结 = f_alloc_BoolProp(&(节点->m_冻结数据), u"冻结数据");
		//Prop冻结.m_UI->m_Update = on_更新节点_冻结;
		//props.push_back(Prop冻结);

		S_Props Prop冻结 = f_alloc_BoolProp(&(节点->m_缓存节点), u"缓存数据");
		Prop冻结.m_UI->m_Update = on_更新节点_缓存;
		props.push_back(Prop冻结);

		if (节点->m_缓存节点 && 节点->m_数据是否以缓存) {
			S_Props 清除缓存 = f_alloc_OpsProp(on_清除节点缓存, u"清除缓存");
			props.push_back(清除缓存);
		}
	}

	//节点->m_启用.m_UI->m_Update = on_更新节点_缓存冻结;
	//props.push_back(节点->m_启用);
	


	S_Props Prop节点名称 = f_alloc_LineStrProp(nullptr, u"节点名称");
	Prop节点名称.m_私有 = true;
	Prop节点名称.m_UI->m_Update = on_更新节点_修改名称;
	f_prop_Str(Prop节点名称) = 节点->f_getWName();
	props.push_back(Prop节点名称);


	auto 子集树 = 节点->f_get子集树();
	if (子集树) {
		//S_Props Prop节点树名称 = f_alloc_LineStrProp(nullptr, u"节点树名称");
		S_Props Prop节点树名称 = f_alloc_StrProp(nullptr, u"节点树名称");
		f_prop_Str(Prop节点树名称) = 节点->f_get子集树()->m_IDName;
		props.push_back(Prop节点树名称);
	}
	
	if(节点->m_冻结数据 || 节点->m_越过更新) return false;




	std::vector<S_标题和图标> ico_name;
	uint32 num = 节点->f_get输入插座数量();

	S_Props box;
	{
		uint32 i = 0;
		switch (节点->m_Type) {
			case E_节点类型::e_节点Type_几何:
			case E_节点类型::e_节点Type_函数: {
				//auto* tree = 节点->f_get子集树();
				//tree->m_编译方式.m_UI->m_Update = on_插座参数修改更新节点;
				//props.push_back(tree->m_编译方式);
			}
			
			case E_节点类型::e_节点Type_组输出:
			//case E_节点类型::e_节点Type_全局:
			//case E_节点类型::e_节点Type_函数:
			//case E_节点类型::e_节点Type_循环迭代:
			//case E_节点类型::e_节点Type_循环:
				if (节点->m_插座可编辑) {
					box = f_alloc_SocketContainer(DEF_输入插座标题);
					++i;
					break;
				}
				
			default:
				box = f_alloc_PropLayout(DEF_输入插座标题, E_值类型::e_Type_LayoutList);
				//box = f_alloc_SocketContainer(DEF_输入插座标题);
				//box.m_私有 = true;
				break;
		}
		
		auto& ContainerIn = f_prop_Container(box);


		for (; i < num; ++i) {
			auto* socket = 节点->f_get输入插座(i);
			std::wstring t;
			S_Props Prop = {};

			//auto type = socket->f_getDataType();
			auto type = socket->m_Type;
			if (socket->f_isLink()) {
				std::u16string t = f_插座数值转文本(socket);

				Prop = f_alloc_StrProp(nullptr, socket->m_identifier);
				f_prop_Str(Prop) = t;

			}
			else {
				switch (type) {
				case E_值类型::e_Type_F32:
					Prop = f_alloc_F32Prop((float32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_I8:
					Prop = f_alloc_I8Prop((int8*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_I32:
					Prop = f_alloc_I32Prop((int32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI32:
					Prop = f_alloc_UI32Prop((uint32*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI64:
					Prop = f_alloc_UI64Prop((uint64*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec2:
					Prop = f_alloc_Vec2Prop((vec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec2:
					Prop = f_alloc_iVec2Prop((ivec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2:
					Prop = f_alloc_uVec2Prop((uvec2*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec3:
					Prop = f_alloc_Vec3Prop((vec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec3:
					Prop = f_alloc_iVec3Prop((ivec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec3:
					Prop = f_alloc_uVec3Prop((uvec3*)socket->f_getData(0), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec4:
					Prop = f_alloc_Vec4Prop((vec4*)socket->f_getData(0), socket->m_identifier);
					break;

				case E_值类型::e_Type_路径:
					//Prop = ((C_路径插座*)socket)->m_Value;
					Prop = DEF_路径插座(socket)->m_Value;
					goto To_直接添加到容器;
				/*case E_值类型::e_Type_Vec2_Array1D:
					Prop = f_alloc_Vec2Prop(DEF_Vec2_1D插座数据(socket)->data(), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2:
					Prop = f_alloc_uVec2Prop((uvec2*)socket->f_getData(0), socket->m_identifier);
					break;
				;*/
				case E_值类型::e_Type_Bool_1D:
					Prop = f_alloc_BoolProp(&(DEF_Bool插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_F32_1D:
					Prop = f_alloc_F32Prop(&(DEF_F32插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_I8_1D:
					Prop = f_alloc_I8Prop(&(DEF_I8插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_I32_1D:
					Prop = f_alloc_I32Prop(&(DEF_I32插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_UI32_1D:
					Prop = f_alloc_UI32Prop(&(DEF_UI32插座_1D数据(socket, 0)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec2_1D:
					Prop = f_alloc_Vec2Prop(&(DEF_Vec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec3_1D:
					Prop = f_alloc_Vec3Prop(&(DEF_Vec3插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_Vec4_1D:
					Prop = f_alloc_Vec4Prop(&(DEF_Vec4插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;

				case E_值类型::e_Type_iVec2_1D:
					Prop = f_alloc_iVec2Prop(&(DEF_iVec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_iVec3_1D:
					Prop = f_alloc_iVec3Prop(&(DEF_iVec3插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;
				case E_值类型::e_Type_uVec2_1D:
					Prop = f_alloc_uVec2Prop(&(DEF_uVec2插座_1D数据(socket)->ptr_userData[0]), socket->m_identifier);
					break;

				case E_值类型::e_Type_纹理:
					if (socket->f_isLink()) {
						Prop = f_alloc_StrProp(&socket->m_identifier, socket->m_identifier);
					}
					else {
						switch (DEF_纹理插座数据(socket, 0)->m_格式) {
							case E_纹理格式::e_tf_RGB8U_归一化:
							case E_纹理格式::e_tf_RGB8:
							case E_纹理格式::e_tf_RGB8U:
							case E_纹理格式::e_tf_RGB32:
								Prop = f_propAlloc_RGB(&(DEF_纹理插座数据(socket, 0)->m_默认颜色), socket->m_identifier);
								break;
							case E_纹理格式::e_tf_R32:
								Prop = f_alloc_F32Prop(&(DEF_纹理插座数据(socket, 0)->m_默认颜色.x), socket->m_identifier);
								break;
							default:
								Prop = f_propAlloc_RGB(&(DEF_纹理插座数据(socket, 0)->m_默认颜色), socket->m_identifier);
								break;
						}
						//Prop = f_propAlloc_RGB(&(DEF_纹理插座数据(socket)->m_默认颜色), socket->m_identifier);
						//Prop = f_alloc_F32Prop(&(DEF_纹理插座数据(socket)->m_默认颜色.x), socket->m_identifier);
					}
					
					break;

				case E_值类型::e_Type_RGB: {
					Prop = f_propAlloc_RGB(&DEF_Vec3插座数据(socket), socket->m_identifier);
					break;
				}
				case E_值类型::e_Type_RGBA: {
					Prop = f_propAlloc_RGBA(&DEF_Vec4插座数据(socket), socket->m_identifier);
					break;
				}
				case E_值类型::e_Type_颜色: {
					Prop = f_propAlloc_RGBA(&DEF_颜色插座数据(socket), socket->m_identifier);
					break;
				}
				default:
					Prop = f_alloc_StrProp(&socket->m_identifier, socket->m_identifier);
					break;
				}

				Prop.m_私有 = true;
				Prop.m_值映射类型 = E_属性引用类型::e_引用;
				Prop.m_UI->m_Update = on_插座参数修改更新节点;

			To_直接添加到容器:
				//Prop.m_GPU内存偏移 = socket->m_GPU内存偏移;
				Prop.m_GPU缓存[0] = socket->m_GPU缓存;
			}
			ContainerIn.m_Item.push_back(Prop);
		}
		props.push_back(box);
	}
	



	{
		uint32 i = 0;
		switch (节点->m_Type) {
		case E_节点类型::e_节点Type_组输入:
		case E_节点类型::e_节点Type_网格属性:
		case E_节点类型::e_节点Type_类成员:
		case E_节点类型::e_节点Type_全局:
		//case E_节点类型::e_节点Type_函数:
		//case E_节点类型::e_节点Type_循环迭代:
		//case E_节点类型::e_节点Type_循环:
		//case E_节点类型::e_节点Type_几何:
			if (节点->m_插座可编辑) {
				//box = f_alloc_PropContainer(DEF_输出插座标题);
				box = f_alloc_SocketContainer(DEF_输出插座标题);
				++i;
				break;
			}
		default:
			box = f_alloc_PropLayout(DEF_输出插座标题, E_值类型::e_Type_LayoutList);
			break;
		}

		//box = f_alloc_PropLayout(u"输出插座", E_值类型::e_Type_LayoutList);
		auto& ContainerOut = f_prop_Container(box);

		ico_name.clear();
		num = 节点->f_get输出插座数量();
		for (; i < num; ++i) {
			auto* socket = 节点->f_get输出插座(i);
			std::u16string t = f_插座数值转文本(socket);

			ico_name.push_back({ socket->m_identifier + u" : " + t, u""});
		}
		ContainerOut.m_Item.push_back(f_alloc_EnumProp(nullptr, ico_name, u"输出插座"));
		props.push_back(box);
	}
	
	
	return true;
}

//C_节点面板* f_节点构建_插件节点面板(S_UI创建环境& ctx, C_节点基类* node) {
//	C_节点面板* plane = new C_节点面板(node, ctx, E_节点区类型::e_节点区_物体);
//	//f_节点重置_UI32数组变量构建(plane, node);
//}

void f_节点参数更新(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);
	}
}

void f_节点参数更新_重新编译(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_更新上层节点(true);
	}
}

void f_节点参数更新_属性栏更新(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_set是否要更新(true);

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}

void f_节点参数更新_重新编译_属性栏更新(S_Props& prop) {
	auto nodes = f_global_get激活节点();
	for (auto 节点 : nodes) {
		节点->f_更新上层节点(true);

		for (auto& panel : 节点->m_包含在多个视口的UI部件) {
			C_节点面板* 节点面板 = static_cast<C_节点面板*>(panel);
			C_节点视口* view = static_cast<C_节点视口*>(节点面板->m_节点当前所在视口);
			节点面板->m_属性面板参数构建(view->m_属性栏, (S_结构指针)节点面板);
		}
	}
}




static S_UI渲染环境* g当前UI环境 = 0;
static fp_节点创建视口回调 fun_节点视口回调 = 0;
//static std::map<std::u16string, S_节点构建参数*> g扩展节点参数;

static void f_扩展节点_部件构建属性(C_属性栏* plane, S_结构指针 obj) {
	C_扩展节点* node = dynamic_cast<C_扩展节点*>(((C_节点面板*)obj)->m_NodeData);

	std::vector<S_Props> props;
	f_节点重构_重构属性面板数据((C_节点面板*)obj, props);

	S_Props prop;

	for (auto& e : node->m_属性) {
		e.m_UI->m_Update = f_节点参数更新;
		props.push_back(e);
	}
	
	plane->f_构建属性部件(props);
}

C_节点面板* f_节点构建_扩展(S_UI渲染环境& ctx, S_设备环境& ctx_3d, C_节点基类* node, C_节点树* tree, const std::u16string& name) {
	if (!node) {
		node = f_node_创建新扩展节点(*S_节点框架::g_3D视口环境, name);
		node->m_ICO = u"ico_拼图0000";
	}
	C_节点面板* plane = new C_节点面板(node, ctx, E_节点区类型::e_节点区_物体);
	f_节点重置_扩展(plane, node);
	return plane;
}

void f_节点重置_扩展(C_节点面板* plane, C_节点基类* node) {
	f_节点重构_面板插座重构(plane, node, E_节点区类型::e_节点区_物体);
	plane->m_属性面板参数构建 = f_扩展节点_部件构建属性;
	plane->m_ICO = node->m_ICO;
}

void f_扩展节点_构建函数初始化(S_UI渲染环境& ctx, fp_节点创建视口回调 fn) {
	g当前UI环境 = &ctx;
	fun_节点视口回调 = fn;

	C_节点面板::g节点面板构建函数[DEF_扩展节点] = f_节点构建_扩展;
	C_节点面板::g节点面板重置函数[DEF_扩展节点] = f_节点重置_扩展;
	//C_节点面板::g节点构建函数_创建名称对应类型名称[u"粒子发射"] = DEF_扩展节点;
}

bool on_创建扩展节点菜单项(C_Widget* self, const std::u16string name, uint16 id) {
	C_节点面板* node = nullptr;

	if (C_节点面板::g节点构建函数_创建名称对应类型名称.find(name) != C_节点面板::g节点构建函数_创建名称对应类型名称.end()) {
		node = C_节点面板::g节点面板构建函数[C_节点面板::g节点构建函数_创建名称对应类型名称[name]](
			*g当前UI环境, 
			*S_节点框架::g_3D视口环境,
			nullptr, 
			nullptr,
			name
		);

		fun_节点视口回调(node, true);
	}
	return false;
}


void f_节点构建_注册扩展节点(E_节点树类型 区域, const S_插件模块& 模块) {
	S_节点构建参数* 节点参数 = (S_节点构建参数*)模块.m_Object;

	switch (区域) {
		case E_节点树类型::e_type_物体节点树: {
			
			C_Widget* 菜单项 = f_ui_get子菜单项(C_节点视口::g物体节点创建菜单, 模块.m_注册路径, true);
			if (菜单项) {
				f_ui_菜单项绑定事件(菜单项, on_创建扩展节点菜单项);
			}
			//g扩展节点参数[模块.m_Name] = 节点参数;

			auto name = 模块.m_Name;
			auto nameA = f_str_u16_to_u8(name);
			C_节点面板::g节点构建函数_创建名称对应类型名称[name] = nameA;

			C_节点面板::g节点面板构建函数[nameA] = f_节点构建_扩展;
			C_节点面板::g节点面板重置函数[nameA] = f_节点重置_扩展;
			break;
		}
		default:
			break;
	}
}

void f_节点构建_注销扩展节点(E_节点树类型 区域, const S_插件模块& 模块) {
	S_节点构建参数* 节点参数 = (S_节点构建参数*)模块.m_Object;


}

void f_节点面板构建_重构扩展节点(const S_插件模块& 模块) {
	auto nodes = f_node_从模块取扩展节点(模块.m_Name);

	for (auto& node : nodes) {
		if (static_cast<C_扩展节点*>(node)->m_扩展.mf_创建) {
			static_cast<C_扩展节点*>(node)->m_扩展.mf_创建(node);
		}

		for (auto& w : node->m_包含在多个视口的UI部件) {
			f_节点重构_面板插座重构(dynamic_cast<C_节点面板*>(w), node);
		}
	}
}





